Skip to content

Android Splash Screen

A guide to add animated and still splash screen for android

Ref: https://developer.android.com/develop/ui/views/launch/splash-screen

You can experiment with different sizes, but make sure to test on both old and new Android devices with varying resolutions and screen sizes.

I found that a canvas (viewport) sized at 432x432 works best. For this example, an icon size of 200x200 centered inside the canvas provides the best fit. However, this may vary depending on the icon’s shape.

When designing your logo using Figma, you can use an extension to export your design as an XML Android Vector Drawable.

For the animated version, you can code it manually using Android Studio. Alternatively, you can create the animation using Lottie or a simple online tool like Shapeshifter.

Assuming you have an SVG for your app logo, we need it to create the following xml files at android/app/src/main/res/drawable:

splash_logo.xml

Go to android/app/src/main/res/drawable and create splash_logo.xml.

A vector of your app logo (not animated) for older android devices that doesn’t support animated splash screen.

We are using dynamic colors in this example @color/bag @color/pins for light and dark themes, we will setup them later here.

<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="432dp"
android:height="432dp"
android:viewportWidth="432"
android:viewportHeight="432">
<path
android:fillColor="@color/bag"
android:pathData="M181.692 155.695C181.692 136.699 197.184 121.226 216.252 121.226C235.319 121.226 250.811 136.703 250.811 155.695V164.967H261.06V155.695C261.06 131.064 240.969 111 216.252 111C191.534 111 171.443 131.064 171.443 155.695L171.447 164.967H181.692V155.695Z" />
<path
android:fillColor="@color/bag"
android:pathData="M136.876 186.971C138.849 174.31 149.752 164.974 162.566 164.974H269.869C282.714 164.974 293.634 174.354 295.572 187.052L311.083 288.7C313.669 305.651 300.55 320.924 283.403 320.924H148.702C131.519 320.924 118.39 305.59 121.036 288.612L136.876 186.971Z" />
<path
android:fillColor="@color/pins"
android:pathData="M171.462 164.974H181.719V195.908C181.719 195.908 187.108 195.908 190.561 195.908C193.391 195.908 195.625 198.147 195.625 200.997C195.625 203.847 193.411 206.072 190.561 206.086C179.637 206.086 173.507 206.086 162.582 206.086C159.785 206.086 157.505 203.794 157.519 200.997C157.533 198.2 159.786 195.936 162.582 195.908C166.05 195.908 171.462 195.908 171.462 195.908V164.974Z" />
<path
android:fillColor="@color/pins"
android:pathData="M250.855 164.974H261.112V195.908C261.112 195.908 266.501 195.908 269.954 195.908C272.784 195.908 275.018 198.147 275.018 200.997C275.018 203.847 272.804 206.072 269.954 206.086C259.029 206.086 252.9 206.086 241.975 206.086C239.178 206.086 236.898 203.794 236.912 200.997C236.926 198.2 239.178 195.936 241.975 195.908C245.442 195.908 250.855 195.908 250.855 195.908V164.974Z" />
</vector>

splash_animated.xml

An animated version of your app logo.

For that, you can code it manually using Android Studio. Alternatively, you can create the animation using Lottie or a simple online tool like Shapeshifter.

The output file should look something like this

<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<!-- vector: where paths are grouped -->
</aapt:attr>
<!-- targets with each target has an animation -->
</animated-vector>
  • Creating splash screen style (default for older devices)

    • Go to android/app/src/main/res/values/styles.xml.
    • Here we are using @drawable/splash_logo a static vector.
    <resources>
    <style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
    <item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
    <!-- Only when facing issues -->
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
    </style>
    <!-- Splash Screen -->
    <style name="Theme.App.Starting" parent="Theme.SplashScreen">
    <item name="windowSplashScreenBackground">@color/background</item>
    <item name="windowSplashScreenAnimatedIcon">@drawable/splash_logo</item>
    <item name="postSplashScreenTheme">@style/AppTheme</item>
    </style>
    </resources>
  • Using splash screen style

    • Go to android/app/src/mainAndroidManifest.xml and use the style we created above.
    • Add or replace android:theme attribute in the application tag with splash screen style name.
    <application android:theme="@style/Theme.App.Starting">
  • Using the animated version for devices that support it.

    • Create android/app/src/main/res/values-v31/styles.xml.
    • Here we are using @drawable/splash_animated the animated version of the logo.
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    <style name="Theme.App.Starting" parent="Theme.SplashScreen">
    <item name="windowSplashScreenBackground">@color/background</item>
    <item name="windowSplashScreenAnimatedIcon">@drawable/splash_animated</item>
    <item name="android:windowSplashScreenAnimationDuration">1000</item>
    <item name="postSplashScreenTheme">@style/AppTheme</item>
    </style>
    </resources>

Dynamic colors

  • Dynamic colors to change your splash screen colors to match user’s device color scheme.

    • For light theme android/app/src/main/res/values/colors.xml
    <resources>
    <color name="background">#FFFFFF</color>
    <color name="bag">#1A191F</color>
    <color name="pins">#FFFFFF</color>
    </resources>
    • For dark theme android/app/src/main/res/values-night/colors.xml
    <resources>
    <color name="background">#1A191F</color>
    <color name="bag">#FFFFFF</color>
    <color name="pins">#1A191F</color>
    </resources>

The Code Part

Preparing The Splash Screen

  • Add splash screen package:

    • Go to android/app/build.gradle and the following to dependencies block
    dependencies {
    // Ensure you are using the current latest version
    implementation("androidx.core:core-splashscreen:1.2.0-beta01")
    }
  • Go to android/app/src/main/java/com/<AppName>/MainActivity.kt

    // import this
    import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
    // optional - for hiding the splash screen manually
    // require creating a native module (later in this guide)
    import com.<AppName>.hideSplashScreen.HideSplashScreenModule
    // optional for exit animations
    import android.animation.AnimatorSet
    import android.animation.ObjectAnimator
    import android.view.View
    import androidx.core.animation.doOnEnd
    class MainActivity : ReactActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
    // add this (before super.onCreate)
    installSplashScreen().apply {
    // optional - for hiding the splash screen manually
    // require creating a native module (later in this guide)
    setKeepOnScreenCondition { NativeSplashScreenModule.keepOn }
    // optional - exit animations
    setOnExitAnimationListener { screen ->
    val duration = 200L
    val zoomInX = ObjectAnimator.ofFloat(screen.iconView, View.SCALE_X, 1f, 5f)
    zoomInX.duration = duration
    val zoomInY = ObjectAnimator.ofFloat(screen.iconView, View.SCALE_Y, 1f, 5f)
    zoomInY.duration = duration
    val fadeOut = ObjectAnimator.ofFloat(screen.view, View.ALPHA, 1f, 0f)
    fadeOut.duration = duration
    AnimatorSet().apply {
    playTogether(zoomInX, zoomInY, fadeOut)
    doOnEnd { screen.remove() }
    start()
    }
    }
    }
    super.onCreate(null)
    }
    // ---
    }

Hiding the splash screen manually

To be able to hide the splash screen from JavaScript we need to create a Native module.

  • Create specs/NativeSplashScreen in the root of your project.

    import { TurboModuleRegistry } from "react-native";
    import type { TurboModule } from "react-native";
    export interface Spec extends TurboModule {
    hide(): void;
    }
    export default TurboModuleRegistry.getEnforcing<Spec>("NativeSplashScreen");
  • Configure Codegen by adding the following to your project package.json, then run cd android && ./gradlew generateCodegenArtifactsFromSchema. This is automatically run when you build your Android application.

"codegenConfig": {
"name": "NativeSplashScreenSpec",
"type": "modules",
"jsSrcsDir": "specs",
"android": {
"javaPackageName": "com.nativeSplashScreen"
}
},
  • Go to android/app/src/main/java/com/nativeSplashScreen and create NativeSplashScreenModule.kt

    package com.nativeSplashScreen
    import com.facebook.react.bridge.ReactApplicationContext
    class NativeSplashScreenModule(reactContext: ReactApplicationContext) :
    NativeSplashScreenSpec(reactContext) {
    override fun getName() = NAME
    override fun hide() {
    keepOn = false
    }
    companion object {
    const val NAME = "NativeSplashScreen"
    var keepOn = true
    }
    }
  • In the same directory create NativeSplashScreenPackage.kt

    package com.nativeSplashScreen
    import com.facebook.react.BaseReactPackage
    import com.facebook.react.bridge.NativeModule
    import com.facebook.react.bridge.ReactApplicationContext
    import com.facebook.react.module.model.ReactModuleInfo
    import com.facebook.react.module.model.ReactModuleInfoProvider
    class NativeSplashScreenPackage : BaseReactPackage() {
    override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? =
    if (name == NativeSplashScreenModule.NAME) {
    NativeSplashScreenModule(reactContext)
    } else {
    null
    }
    override fun getReactModuleInfoProvider() = ReactModuleInfoProvider {
    mapOf(
    NativeSplashScreenModule.NAME to ReactModuleInfo(
    name = NativeSplashScreenModule.NAME,
    className = NativeSplashScreenModule.NAME,
    canOverrideExistingModule = false,
    needsEagerInit = false,
    isCxxModule = false,
    isTurboModule = true
    )
    )
    }
    }
  • Go to android/app/src/main/java/com/<AppName>/MainApplication.kt to register the native module we have created.

    import com.nativeSplashScreen.NativeSplashScreenPackage // import this
    // ---
    class MainApplication : Application(), ReactApplication {
    override val reactNativeHost: ReactNativeHost = object : DefaultReactNativeHost(this) {
    override fun getPackages(): List<ReactPackage> = PackageList(this).packages.apply {
    add(NativeSplashScreenPackage()) // add this
    }
    // ---
  • Call it from JavaScript

    import NativeSplashScreen from "../specs/NativeSplashScreen";
    // when your app is fully loaded call this to hide the splash screen
    NativeSplashScreen.hide();
    Note

    If the screen went black after the splash screen is shown it might be due to the debug build, make sure to test the release build.